package org.zeroes.common_prelude;

public class Mat4 {

	public float[] data ;
	public Mat4(){
		
		data = new float[16];
	}
	
	public static Mat4 perspective(float fovy, float aspect, float near, float far){
		
	    float top = (float) (near * Math.tan(fovy * Math.PI / 360.0)),
	            right = top * aspect;
	        return frustum(-right, right, -top, top, near, far);
	}
	
	public static Mat4 frustum(float left, float right,float bottom,float top,float near,float far){
		Mat4 dest = new Mat4();
		
		float rl = (right - left),
		        tb = (top - bottom),
		        fn = (far - near);
		    dest.data[0] = (near * 2) / rl;
		    dest.data[1] = 0;
		    dest.data[2] = 0;
		    dest.data[3] = 0;
		    dest.data[4] = 0;
		    dest.data[5] = (near * 2) / tb;
		    dest.data[6] = 0;
		    dest.data[7] = 0;
		    dest.data[8] = (right + left) / rl;
		    dest.data[9] = (top + bottom) / tb;
		    dest.data[10] = -(far + near) / fn;
		    dest.data[11] = -1;
		    dest.data[12] = 0;
		    dest.data[13] = 0;
		    dest.data[14] = -(far * near * 2) / fn;
		    dest.data[15] = 0;
		    return dest;
	}
	
	public static Mat4 lookAt(float eyex,float eyey,float eyez,float centerx, float centery, float centerz, float upx, float upy, float upz){
		
		Mat4 dest = new Mat4();
		
		float  x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
		
		z0 = eyex - centerx;
	    z1 = eyey - centery;
	    z2 = eyez - centerz;

	    // normalize (no check needed for 0 because of early return)
	    len = (float)(1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2));
	    z0 *= len;
	    z1 *= len;
	    z2 *= len;

	    //vec3.normalize(vec3.cross(up, z, x));
	    x0 = upy * z2 - upz * z1;
	    x1 = upz * z0 - upx * z2;
	    x2 = upx * z1 - upy * z0;
	    len = (float)(Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2));
	    if (len==0) {
	        x0 = 0;
	        x1 = 0;
	        x2 = 0;
	    } else {
	        len = 1 / len;
	        x0 *= len;
	        x1 *= len;
	        x2 *= len;
	    }

	    //vec3.normalize(vec3.cross(z, x, y));
	    y0 = z1 * x2 - z2 * x1;
	    y1 = z2 * x0 - z0 * x2;
	    y2 = z0 * x1 - z1 * x0;

	    len = (float)(Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2));
	    if (len==0) {
	        y0 = 0;
	        y1 = 0;
	        y2 = 0;
	    } else {
	        len = 1 / len;
	        y0 *= len;
	        y1 *= len;
	        y2 *= len;
	    }

	    dest.data[0] = x0;
	    dest.data[1] = y0;
	    dest.data[2] = z0;
	    dest.data[3] = 0;
	    dest.data[4] = x1;
	    dest.data[5] = y1;
	    dest.data[6] = z1;
	    dest.data[7] = 0;
	    dest.data[8] = x2;
	    dest.data[9] = y2;
	    dest.data[10] = z2;
	    dest.data[11] = 0;
	    dest.data[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
	    dest.data[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
	    dest.data[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
	    dest.data[15] = 1;

	    return dest;
	}
}
